import { Token, TokenType } from "./tokenizer";

export enum NodeTypes {
  Program = "Program",
  NumberLiteral = "NumberLiteral",
  CallExpression = "CallExpression",
  StringLiteral = "StringLiteral",
}

interface Node {
  type: NodeTypes;
}

export interface RootNode extends Node {
  body: ChildNode[];
  context?: ChildNode[];
}

export interface NumberNode extends Node {
  value: string;
  context?: ChildNode[];
}

export interface CallExpressionNode extends Node {
  name: string;
  params: ChildNode[];
  context?: ChildNode[];
}

export type ChildNode = NumberNode | CallExpressionNode;

function createNumberNode(value: string): NumberNode {
  return {
    type: NodeTypes.NumberLiteral,
    value,
  };
}

function createCallExpressionNode(name: string): CallExpressionNode {
  return {
    type: NodeTypes.CallExpression,
    name,
    params: [],
  };
}

function createRootNode(): RootNode {
  return {
    type: NodeTypes.Program,
    body: [],
  };
}

// 语法分析
export function parser(tokens: Token[]) {
  let current = 0;
  const rootNode = createRootNode();

  const walk = () => {
    let token = tokens[current];
    if (token.type === TokenType.Number) {
      current++;
      return createNumberNode(token.value);
    }

    if (token.type === TokenType.LeftParen && token.value === "(") {
      token = tokens[++current];

      const node = createCallExpressionNode(token.value);
      token = tokens[++current]; // 上一个 token 已经消费，因此继续移动到下一个位置
      // params
      while (!(token.type === TokenType.RightParen && token.value === ")")) {
        node.params.push(walk());
        token = tokens[current];
      }

      current++; // 跳过右括号 ")"

      return node;
    }

    throw new Error(`Invalid token: ${token}`);
  };

  while (current < tokens.length) {
    rootNode.body.push(walk());
  }

  return rootNode;
}
